﻿using System.Collections.Generic;
using Microsoft.Xna.Framework.Content;

namespace Origin2.Framework.Managers
{
    /// <summary>
    /// An AssetManager, which essentially handles loading/managing assets.
    /// </summary>
    public static class AssetManager
    {
        /// <summary>
        /// The ContentManager to load content from (can be "stolen" from the main game class)
        /// </summary>
        public static ContentManager ContentManager;

        private static Dictionary<string, object> _content; 

        static AssetManager()
        {
            _content = new Dictionary<string, object>();
        }

        /// <summary>
        /// Loads a content item from a file and stores it in the AssetManager
        /// </summary>
        /// <typeparam name="TContentType"> The type of content to load </typeparam>
        /// <param name="path"> The path of the file to load (relative to ContentManager.RootDirectory, doesn't have a file extension) </param>
        /// <param name="storageName"> The name to store the loaded item as in the asset manager </param>
        public static void LoadContent<TContentType>(string path, string storageName)
        {
            _content.Add(storageName, ContentManager.Load<TContentType>(path));
        }

        /// <summary>
        /// Loads a content item directly, without storing it in the AssetManager
        /// </summary>
        /// <typeparam name="TContentType"> The type of content item to load </typeparam>
        /// <param name="path"> The path of the content item (relative to ContentManager.RootDirectory, without the extension) </param>
        /// <returns> The loaded content item </returns>
        public static TContentType LoadContentDirect<TContentType>(string path)
        {
            return ContentManager.Load<TContentType>(path);
        }

        /// <summary>
        /// Gets the content item with the given name
        /// </summary>
        /// <param name="name"> The name of the item to get </param>
        /// <returns> The found item </returns>
        public static object GetContent(string name)
        {
            return _content[name];
        }

        /// <summary>
        /// Gets a content item from the Asset Manager
        /// </summary>
        /// <typeparam name="TContentType"> The type of content to get </typeparam>
        /// <param name="name"> The name of the item to get </param>
        /// <returns> The found content item </returns>
        public static TContentType GetContent<TContentType>(string name)
        {
            return (TContentType)_content[name];
        }

        /// <summary>
        /// Loads a content item from a file, stores it in the AssetManager, and then returns it
        /// </summary>
        /// <typeparam name="TContentType"> The type of content item to load </typeparam>
        /// <param name="path"> The path of the content item (relative to ContentManager.RootDirectory, without extension) </param>
        /// <param name="storageName"> The name to store the loaded item as in the AssetManager</param>
        /// <returns> The loaded content item </returns>
        public static TContentType LoadAndGetContent<TContentType>(string path, string storageName)
        {
            LoadContent<TContentType>(path, storageName);
            return GetContent<TContentType>(storageName);
        }

        /// <summary>
        /// Gets whether there is a content item loaded with the given name
        /// </summary>
        /// <param name="name"> The name to search for </param>
        /// <returns> Whether there is a content item loaded with the given name </returns>
        public static bool ContainsContent(string name)
        {
            return _content.ContainsKey(name);
        }

        /// <summary>
        /// Gets whether there is a content item loaded with the given name AND that the item is of the given type
        /// </summary>
        /// <typeparam name="TContentType"> The type to search for </typeparam>
        /// <param name="name"> The name to search for </param>
        /// <returns> Whether there is a content item loaded with the given name AND that said item is of the given type</returns>
        public static bool ContainsContent<TContentType>(string name)
        {
            if (ContainsContent(name))
                return _content[name].GetType() == typeof (TContentType);

            return false;
        }

        /// <summary>
        /// Unloads ALL content from the AssetManager
        /// </summary>
        public static void UnloadContent()
        {
            _content.Clear();
        }

        /// <summary>
        /// Unloads the content item with the given name from the AssetManager
        /// </summary>
        /// <param name="name"></param>
        public static void UnloadContent(string name)
        {
            _content.Remove(name);
        }
    }
}
